﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Mime;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using DeviceCommon;

namespace IDCardReader
{
    public class ReaderDll
    {
        public struct STR_ID_INFO
        {
            public string name;//" 姓名" + " "
            public string sex;//"性别" + " " 
            public string people;//"民族" + " " 
            public string birth;//"出生" + " " 
            public string address;//"住址" + " " 
            public string idNum;//"公民身份号码
            public string issuePlace;//"签发机关" + 
            public string issueDay;
            public string expiryDay;//"有效期限" + 
        }

        bool m_bNIDapi = false;

        byte[] pucCHMsg = new byte[512];
        byte[] pucPHMsg = new byte[1024];
        int puiCHMsgLen = 512;
        int puiPHMsgLen = 1024;
        int m_nOpenPort = 0;
        string str;

        [DllImport("kernel32")]
        public static extern int LoadLibrary(string strDllName);

        [DllImport("sdtapi.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Winapi)]
        public static extern int SDT_OpenPort(int iPort);
        [DllImport("sdtapi.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Winapi)]
        public static extern int SDT_ClosePort(int iPort);

        [DllImport("sdtapi.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Winapi)]
        public static extern int SDT_StartFindIDCard(int iPort, ref byte pRAPDU, int iIfOpen);

        [DllImport("sdtapi.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Winapi)]
        public static extern int SDT_SelectIDCard(int iPort, ref byte pRAPDU, int iIfOpen);

        [DllImport("sdtapi.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Winapi)]
        public static extern int SDT_ReadBaseMsg(int iPort, ref byte pucCHMsg, ref int puiCHMsgLen, ref byte pucPHMsg, ref int puiPHMsgLen, int iIfOpen);

        [DllImport("sdtapi.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Winapi)]
        public static extern int SDT_ReadNewAppMsg(int iPort, ref byte pucAppMsg, ref int puiAppMsgLen, int iIfOpen);

        [DllImport("WltRS.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern int GetBmp(string filename, int nType);

        public int InitReader()
        {
            int nRet;

            //加载动态库
            if (m_bNIDapi == false)
            {
                string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
                string currentPath = System.IO.Directory.GetCurrentDirectory();
                Directory.SetCurrentDirectory(path);
                nRet = LoadLibrary("sdtapi.dll");
                if (nRet == 0)
                {
                    //MessageBox.Show("加载sdtapi.dll失败");
                    return -1;
                }
                else
                {
                    // m_bNIDapi = true;
                    for (int iPort = 1001; iPort < 1017; iPort = iPort + 1)
                    {
                        if (SDT_OpenPort(iPort) == 0x90)
                        {
                            m_nOpenPort = iPort;
                            m_bNIDapi = true;
                            break;
                        }
                    }
                }

                Directory.SetCurrentDirectory(currentPath);
            }
            if (m_bNIDapi != true)
            {
                return -2;
            }

            return 0;
        }

        public int UnInitReader()
        {
            if (m_bNIDapi == true)
            {
                string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
                //string currentPath = System.IO.Directory.GetCurrentDirectory();
                Directory.SetCurrentDirectory(path);
                //Directory.SetCurrentDirectory(currentPath);
                return SDT_ClosePort(0);
            
            }

            return 0;
        }

        public int ReadIdCard(string photoPath,out STR_ID_INFO id_info)
        {
            string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            string currentPath = System.IO.Directory.GetCurrentDirectory();
            Directory.SetCurrentDirectory(path);
            id_info = new STR_ID_INFO();
            int nRet;
            if (m_bNIDapi != true)
            {
                //MessageBox.Show("没有初始化核心");
                return -3;
            }
            byte[] pRAPDU = new byte[30];
            byte[] pucAppMsg = new byte[320];
            int len = 320;
            nRet = SDT_ReadNewAppMsg(m_nOpenPort, ref pucAppMsg[0], ref len, 0);
            if (nRet == 0x91 || nRet == 0x90)
            {
                //MessageBox.Show("此卡已读过！");
                return -4;
            }
            nRet = SDT_StartFindIDCard(m_nOpenPort, ref pRAPDU[0], 0);
            if (nRet != 0x9F)
            {
                //MessageBox.Show("寻找卡失败");
                return -5;
            }
            if (SDT_SelectIDCard(m_nOpenPort, ref  pRAPDU[0], 0) != 0x90)
            {
                //MessageBox.Show("选卡失败");
                return -6;
            }

            nRet = SDT_ReadBaseMsg(m_nOpenPort, ref pucCHMsg[0], ref puiCHMsgLen, ref pucPHMsg[0], ref puiPHMsgLen, 0);
            if (nRet != 0x90)
            {
                //MessageBox.Show("读取数据到数组失败");
                return -7;
            }

            //显示信息            
            id_info.name = GetName();
            id_info.sex = GetSex();
            id_info.people = GetPeople();
            id_info.birth = GetBirthday();
            id_info.address =  GetAddress();
            id_info.idNum = GetIDCode();
            id_info.issuePlace = GetAuthority();
            id_info.issueDay = GetIssueDay();
            id_info.expiryDay = GetExpityDay();

            //显示图像
            //string path = MediaTypeNames.Application.StartupPath;
            SavePhoto(photoPath, id_info.idNum,2);
            //path += "\\head.bmp";
            //PictureBox1.ImageLocation = path; 
            Directory.SetCurrentDirectory(currentPath);

            return 0;
        }

        string GetName()
        {
            if (puiCHMsgLen == 0)
            {
                return "";
            }
            str = System.Text.Encoding.Unicode.GetString(pucCHMsg, 0, 30);
            return str.Trim();

        }
        string GetSex()
        {
            if (puiCHMsgLen == 0)
            {
                return " ";
            }

            byte sex = pucCHMsg[30];

            if (sex == '1')
            {
                return "男";
            }
            else
                return "女";

        }

        string GetPeople()
        {
            if (puiCHMsgLen == 0)
            {
                return " ";
            }

            str = System.Text.Encoding.Unicode.GetString(pucCHMsg, 32, 4);
            switch (str)
            {
                case "01": return "汉";
                case "02": return "蒙古";
                case "03": return "回";
                case "04": return "藏";
                case "05": return "维吾尔";
                case "06": return "苗";
                case "07": return "彝";
                case "08": return "壮";
                case "09": return "布依";
                case "10": return "朝鲜";
                case "11": return "满";
                case "12": return "侗";
                case "13": return "瑶";
                case "14": return "白";
                case "15": return "土家";
                case "16": return "哈尼";
                case "17": return "哈萨克";
                case "18": return " 傣";
                case "19": return " 黎";
                case "20": return " 傈僳";
                case "21": return " 佤";
                case "22": return " 畲";
                case "23": return " 高山";
                case "24": return " 拉祜";
                case "25": return " 水";
                case "26": return " 东乡";
                case "27": return " 纳西";
                case "28": return " 景颇";
                case "29": return " 柯尔克孜";
                case "30": return " 土";
                case "31": return " 达斡尔";
                case "32": return " 仫佬";
                case "33": return "羌";
                case "34": return "布朗";
                case "35": return "撒拉";
                case "36": return "毛南";
                case "37": return "仡佬";
                case "38": return "锡伯";
                case "39": return "阿昌";
                case "40": return "普米";
                case "41": return "塔吉克";
                case "42": return "怒";
                case "43": return "乌孜别克";
                case "44": return "俄罗斯";
                case "45": return "鄂温克";
                case "46": return "德昂";
                case "47": return "保安";
                case "48": return "裕固";
                case "49": return "京";
                case "50": return "塔塔尔";
                case "51": return "独龙";
                case "52": return "鄂伦春";
                case "53": return "赫哲";
                case "54": return "门巴";
                case "55": return "珞巴";
                case "56": return "基诺";
                case "97": return "其他";
                case "98": return "外国血统中国籍人士";
                default: return "";
            }

        }
        string GetBirthday()
        {
            if (puiCHMsgLen == 0)
            {
                return " ";
            }
            str = System.Text.Encoding.Unicode.GetString(pucCHMsg, 36, 16);
            return str.Trim();
        }

        string GetAddress()
        {
            if (puiCHMsgLen == 0)
                return " ";

            str = System.Text.Encoding.Unicode.GetString(pucCHMsg, 52, 70);
            return str.Trim();
        }
        string GetAuthority()
        {
            if (puiCHMsgLen == 0)
                return " ";
            str = System.Text.Encoding.Unicode.GetString(pucCHMsg, 158, 30);
            return str.Trim();
        }
        string GetIDCode()
        {
            if (puiCHMsgLen == 0)
                return "";

            str = System.Text.Encoding.Unicode.GetString(pucCHMsg, 122, 36);
            return str.Trim();
        }
        string GetIssueDay()
        {
            if (puiCHMsgLen == 0)
                return "";


            str = System.Text.Encoding.Unicode.GetString(pucCHMsg, 188, 16);
            return str.Trim();
        }
        string GetExpityDay()
        {
            if (puiCHMsgLen == 0)
                return "";

            str = System.Text.Encoding.Unicode.GetString(pucCHMsg, 204, 16);
            return str.Trim();
        }

        int SavePhoto(string photoPath, string idNum, int nType)
        {
            string savepath = photoPath + "\\" + idNum + ".wlt";
            FileStream fs;
            fs = new FileStream(savepath, FileMode.Create, FileAccess.ReadWrite);
            fs.Write(pucPHMsg, 0, pucPHMsg.Length);
            fs.Close();
            int b = GetBmp(savepath, nType);
            return 0;
        }
    }
}
